package com.face.server.service.impl;

import com.alibaba.fastjson.JSON;
import com.arcsoft.AFR_FSDK_FACEMODEL;
import com.arcsoft.ASVLOFFSCREEN;
import com.arcsoft.FaceInfo;
import com.face.RespMsg;
import com.face.client.model.NotFoundFaceException;
import com.face.client.pojo.FeatureList;
import com.face.server.dao.JoinedDAO;
import com.face.server.entity.DormitoryAdmin;
import com.face.server.entity.FaceModel;
import com.face.server.entity.Joined;
import com.face.server.entity.Student;
import com.face.server.repository.FaceModelRepository;
import com.face.server.repository.JoinedRepository;
import com.face.server.repository.StudentRepository;
import com.face.server.service.IFaceDetectService;
import com.util.FaceUtils;
import com.util.ImageUtils;
import com.util.SDKUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
public class FaceDetectImpl implements IFaceDetectService {

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    GridFsTemplate gridFsTemplate;

    @Autowired
    StudentRepository studentRepository;

    @Autowired
    FaceModelRepository faceModelRepository;

    @Autowired
    JoinedDAO joinedDAO;

    @Autowired
    JoinedRepository joinedRepository;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Override
    public FaceInfo[] doDetect(MultipartFile file) throws IOException {
        return FaceUtils.getFaceInfos(file.getInputStream());
    }

    @Override
    public AFR_FSDK_FACEMODEL getModel(MultipartFile file) throws IOException, NotFoundFaceException {
        ASVLOFFSCREEN asvloffscreen = ImageUtils.loadImage(file.getInputStream());
        return SDKUtils.getModelFD(asvloffscreen);
    }

    @Override
    public FaceModel saveModel(AFR_FSDK_FACEMODEL model, MultipartFile file) throws IOException {
        FaceModel faceModel = SDKUtils.getContentFromModel(model);
        String filename = file.getOriginalFilename();
        String id = gridFsTemplate.store(file.getInputStream(), filename).getId().toString();
        faceModel.setImageName(filename);
        faceModel.setFileId(id);
        return faceModelRepository.save(faceModel);
    }


    @Override
    public String save(MultipartFile file, Student student) throws IOException, NotFoundFaceException {
        AFR_FSDK_FACEMODEL facemodel = getModel(file);
        FaceModel faceModel = saveModel(facemodel, file);
        student.getFaceModels().add(faceModel);
        String fileId = faceModel.getFileId();
        int ret = mongoTemplate.updateFirst(Query.query(where("_id").is(student.getId()))
                , new Update().push("faceModels", faceModel), Student.class).getN();
        assert ret == 1;
        return fileId;
    }

    @Override
    public RespMsg updateFaceModels(Joined joined, String fid, MultipartFile file) throws IOException {
        RespMsg msg = checkFaceInfos(file);
        if (msg.isError())
            return msg;
        AFR_FSDK_FACEMODEL model = (AFR_FSDK_FACEMODEL) msg.getData();
        List<FaceModel> faceModels = joined.getFaceModels();
        if (faceModels.size() > 0) {
            FaceModel basicFaceModel = faceModels.get(0);
            AFR_FSDK_FACEMODEL basicModel = basicFaceModel.toModel();
            float s = SDKUtils.compareFace(basicModel, model);
            System.out.println(s);
            if (s < 0.6) {
                return RespMsg.error("对不起，精确度太低，请换图片");
            }
        }
        faceModels.stream().filter(e->e.getFileId().equals(fid)).map(e->faceModels.remove(e));

        FaceModel faceModel = saveModel(model, file);
        faceModels.add(faceModel);
        joinedRepository.save(joined);
/*发送到rabbitmq*/
        joined.setFaceModels(new ArrayList<>());
        FaceModel idmodel = new FaceModel();
        idmodel.setId(faceModel.getId());
        joined.getFaceModels().add(idmodel);
        rabbitTemplate.convertAndSend("face", JSON.toJSONString(joined));

        return RespMsg.build(faceModel.getFileId());
    }

    public RespMsg saveFaceModels(MultipartFile file, Joined joined) throws IOException {
        RespMsg msg = checkFaceInfos(file);
        if (msg.isError())
            return msg;
        AFR_FSDK_FACEMODEL model = (AFR_FSDK_FACEMODEL) msg.getData();
        List<FaceModel> faceModels = joined.getFaceModels();
        if (faceModels.size() > 0) {
            FaceModel basicFaceModel = faceModels.get(0);
            AFR_FSDK_FACEMODEL basicModel = basicFaceModel.toModel();
            float s = SDKUtils.compareFace(basicModel, model);
            System.out.println(s);
            if (s < 0.6) {
                return RespMsg.error("对不起，精确度太低，请换图片");
            }
        }

        if (faceModels.size() == 5) {
            faceModels.remove(4);
        }
        FaceModel faceModel = saveModel(model, file);
        faceModels.add(faceModel);
        joinedRepository.save(joined);
/*发送到rabbitmq*/
        joined.setFaceModels(new ArrayList<>());
        FaceModel idmodel = new FaceModel();
        idmodel.setId(faceModel.getId());
        joined.getFaceModels().add(idmodel);
        rabbitTemplate.convertAndSend("face", JSON.toJSONString(joined));

        return RespMsg.build(faceModel.getFileId());
    }


    private RespMsg checkFaceInfos(MultipartFile file) throws IOException {
        FaceInfo[] faceInfos = FaceUtils.getFaceInfos(file.getInputStream());
        if (faceInfos.length == 0) {
            return RespMsg.error(1, "人脸为0, 请重新上传");
        } else if (faceInfos.length > 1) {
            return RespMsg.error(1, "人脸数目超过1");
        }
        ASVLOFFSCREEN asvloffscreen = ImageUtils.loadImage(file.getInputStream());
        AFR_FSDK_FACEMODEL model = SDKUtils.getModel(asvloffscreen, faceInfos);
        return RespMsg.build(model);
    }
}
